package com.udi.project.business.utils.httpApi;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.udi.common.exception.base.BaseException;
import com.udi.project.business.utils.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.logging.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.xml.transform.Source;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author Admin
 * 向药监局API发送请求
 */
@PropertySource(value={"classpath:application.yml"})
@Component
@Slf4j
public class OkHttp1<OkHttpClient> {

    @Value("${http.uniqueLogo}")
    private String uniqueLogo;

    @Value("${http.credentials}")
    private String credentials;

    @Value("${http.appId}")
    private String appId;

    @Value("${http.appSecret}")
    private String appSecret;

    @Value("${http.connectivity}")
    private String connectivity;

    @Value("${http.product}")
    private String product;

    @Value("${http.FillIn}")
    private String FillIn;

    @Value("${http.before}")
    private String before;

    @Autowired
    private RedisUtils redisUtils;

    private Log log;



    /**全局请求对象*/
    okhttp3.OkHttpClient okHttpClient = new okhttp3.OkHttpClient();



    /**
    *
     * @Description: 通用Get请求
     * @param url 请求地址
     * @return: JSON 返回结果
     * @Date: 2021/7/31 17:35
     */
    public JSONObject GetOkHttp(String url) throws IOException{
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        try (Response response = okHttpClient.newCall(request).execute()) {
            return JSON.parseObject(response.body().string());
        }

    }


    /**
     *
     * @Description: 通用Post请求
     * @param url 请求地址
     * @param requestBody 请求元素对象
     * @return: JSON 返回结果
     * @Date: 2021/7/31 17:35
     */
    public JSONObject PostOkHttp(String url,RequestBody requestBody) throws IOException{

        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();


        try (Response response = okHttpClient.newCall(request).execute()) {
            return JSON.parseObject(response.body().string());
        }

    }

    /**
    *
     * @Description:防止缓存雪崩造成崩溃
     * @param  key 获取指定的key
     * @return: java.lang.String 返回token
     * @Date: 2021/8/3 9:24
     */
    public String  getToken(String key) throws IOException {
        Object to = redisUtils.get(key);
        if(to == null || to == ""){
            //应对高并发
            synchronized (this){
                to = redisUtils.get(key);
                //二次检测
                if (to == null || to == ""){
                    GetCredentials();
                    return (String) redisUtils.get("Token");
                }
                return (String) to;
            }

        }
        return (String) to;
    }






    /**
    *
     * @Description: 连通性测试
     * @return: Boolean 成功连接医疗器械唯一标识数据库，如果出错那么接下来的所有步骤将不可执行
     * @Date: 2021/8/2 10:36
     */
    public Boolean ConnectivityTest() throws IOException {
        RequestBody requestBody = new FormBody.Builder().build();
        JSONObject jsonObject = PostOkHttp(connectivity,requestBody);
        if(!jsonObject.getString("returnCode").equals("1")){
            log.info("无法连接医疗器械唯一标识数据库错误异常---->"+jsonObject.getString("returnMsg"));
            throw new BaseException("无法连接医疗器械唯一标识数据库");
        }
        return true;
    }



    /**
    *
     * @Description: 获取接口调用凭据,如果出错那么接下来的所有步骤将不可执行
     * @return: 令牌
     * @Date: 2021/8/2 9:06
     */
    public boolean GetCredentials() throws IOException {
        String str = "{\"appId\":\""+appId+"\",\"appSecret\":\""+appSecret+"\"}";
        RequestBody requestBody = new FormBody.Builder()
                .add("params",str)
                .build();
        JSONObject credentialsJson = PostOkHttp(credentials,requestBody);
       if(!credentialsJson.getString("returnCode").equals("1")){
           log.info("获取接口调用凭证错误---->"+credentialsJson.getString("returnMsg"));
           throw new BaseException("获取接口调用凭证异常");
       }
       //缓存有效期12小时 保存token 和 当天访问次数
       if(redisUtils.set("Token",credentialsJson.getString("accessToken"),6,TimeUnit.HOURS)){
           redisUtils.set("Visits",credentialsJson.get("todayRemainVisitCount"),6,TimeUnit.HOURS);
           return true;
       }
       throw new BaseException("Token添加缓存失败");
    }




    /**
    *
     * @Description: 获取产品标识数据
     * @param requestType 产品标识记录新增开始时间 时间格式： yyyy-MM-dd HH:mm:ss
     * @param rangeValue 产 品 标 识 记 录 新 增 结 束 时 间
     * @param currentPageNumber 请求分页数,初始请求时，从 1 开始
     * @return: JSONObject 获取医疗器械唯一标识库中的产品标识以及其相关数据信息。
     * @Date: 2021/7/31 17:29
     */
    public JSONObject GetLogo(String requestType,String rangeValue,String currentPageNumber) throws IOException {

        Object to = redisUtils.hmval("log",rangeValue);
        if(to == null || to == ""){
            //应对高并发
            synchronized (this){
                to = redisUtils.hmval("log",rangeValue);
                //二次检测
                if (to == null || to == ""){
                    String str = "{\"accessToken\":\""+getToken("Token")+"\",\"startTime\":\""+requestType+"\",\"endTime\":\""+rangeValue+"\",\"currentPageNumber\":\""+currentPageNumber+"\"}";
                    RequestBody requestBody = new FormBody.Builder()
                            .add("params",str)
                            .build();
                    System.out.println("------------正在请求中----------------");
                    JSONObject jsonObject = PostOkHttp(uniqueLogo,requestBody);
                    if(jsonObject.getString("dataSet")==null){
                        throw new BaseException(jsonObject.getString("returnMsg"));
                    }
                    //失效时间 5分钟
                    Map<String, Object> map = new HashMap<>();
                    map.put(rangeValue,jsonObject);
                    redisUtils.hmset("log",map,300);
                    return jsonObject;
                }
                return (JSONObject) to;
            }
        }
        return (JSONObject) to;
    }


    /**
    *
     * @Description: 提交产品标识
     * @param deviceRecordKey 标识数据记录 key1
     * @param ZXXSDYCPBS 最小销售单元产品标识 1
     * @return: String 失败返回错误原因，成功返回状态码
     * @Date: 2021/8/2 11:16
     */
    public String PostProductLogo(String deviceRecordKey,String ZXXSDYCPBS) throws IOException {
        String parameter = "{\"accessToken\":\""+getToken("Token")+"\",\"dataSet\":[{\"deviceRecordKey\":\""+deviceRecordKey+"\",\"ZXXSDYCPBS\":\""+ZXXSDYCPBS+"\"}]}";
        RequestBody requestBody = new FormBody.Builder()
                .add("params",parameter)
                .build();

        JSONObject jsonObject = PostOkHttp(product,requestBody);

        if(!jsonObject.getString("returnCode").equals("1")){
            System.out.println("返回信息--------------->"+jsonObject);
            return jsonObject.toJSONString();
        }
        return "200";
    }


    /**
    *
     * @Description: 产品标识数据填报
     * @param product 产品标识数据实体，toString方法不可修改
     * @return: JSONObject 成功返回1  失败返回具体说明见JSON中的errorMsg
     * @Date: 2021/8/3 8:59
     */
    public JSONObject PostProductFillIn(String product) throws IOException {
        RequestBody requestBody = new FormBody.Builder()
                .add("params",product)
                .build();
        return PostOkHttp(FillIn,requestBody);

    }




    /**
     *
     * @Description: 产品标识数据批量填报
     * @param product 产品标识数据实体，toString方法不可修改
     * @return: JSONObject 成功返回1  失败返回具体说明见JSON中的errorMsg
     * @Date: 2021/8/3 8:59

    public JSONObject PostProduct(JSONArray product) throws IOException {
        RequestBody requestBody = new FormBody.Builder()
                .add("params",product)
                .build();
        return PostOkHttp(FillIn,requestBody);

    }
     */


    /**
    *
     * @Description: 获取历史版本数据
     * @param keyOne 标识数据记录 key1
     * @param PageNumber 请求分页数,初始请求时，从 1 开始
     * @return: com.alibaba.fastjson.JSONObject 返回具体的历史数据
     * @Date: 2021/8/3 9:14
     */
    public JSONObject History(String keyOne,String PageNumber) throws IOException {
        String str = "{\"accessToken\":\""+getToken("Token")+"\",\"dataSet\":[{\"deviceRecordKey\":\""+keyOne+"\"}],\"currentPageNumber\":\""+PageNumber+"\"}";
        RequestBody requestBody = new FormBody.Builder()
                .add("params",str)
                .build();
        return PostOkHttp(before,requestBody);
    }
}
